package com.twu.biblioteca.ui.menus;

import com.google.common.base.Optional;
import com.twu.biblioteca.library.Library;
import com.twu.biblioteca.ui.menus.items.AbstractMenuItem;
import com.twu.biblioteca.users.User;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Alvi Jonathan Sait
 */
public abstract class AbstractMenu {

    private final Library library;
    private final ArrayList<AbstractMenuItem> menuItems;


    protected AbstractMenu(Library library) {
        this.library = library;
        this.menuItems = new ArrayList<AbstractMenuItem>();
    }

    /**
     * Handles the processing of the user input. Determines the next menu to be called/shown depending on the input.
     */
    public AbstractMenu handleInput(String input) {
        try {
            // Retrieves the Menu Item from the list given the index and then execute the handleAction function in the Menu Item.
            final int index = Integer.parseInt(input) - 1;
            if (index >= 0 && index < menuItems.size()) {
                AbstractMenuItem menuItem = menuItems.get(index);
                return menuItem.handleAction(library);
            }
            // If input is a number but not within the range of available indexes.
            return new InvalidOptionMenu(getLibrary(), this);
        } catch (NumberFormatException nfe) {
            // If input is not a number
            return new InvalidOptionMenu(getLibrary(), this);
        }
    }

    protected void addMenuItem(AbstractMenuItem menuItem) {
        if (menuItem.isViewableByActiveUser(getLibrary().getUserAccountsManager())) {
            menuItems.add(menuItem);
        }
    }

    /**
     * Generates/Formats the Menu Items into this format:
     * <p/>
     * 1 : List Books
     * 2 : List Movies
     * 3 : Login
     * 4 : Exit
     */
    protected String generateMenuItemsOutput() {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < getMenuItems().size(); i++) {
            builder.append(i + 1).append(" : ").append(getMenuItems().get(i)).append(System.lineSeparator());
        }
        return builder.toString();
    }

    protected List<AbstractMenuItem> getMenuItems() {
        return menuItems;
    }

    protected Library getLibrary() {
        return library;
    }

    /**
     * Retrieves the active user from the library. Returns null if there are no user.
     */
    protected User getUser() {
        Optional<User> currentlyActiveUser = getLibrary().getUserAccountsManager().getCurrentlyActiveUser();
        return currentlyActiveUser.orNull();
    }

    public abstract String getOutput();

    public abstract String getUserPrompt();

}
